Virtual 8086 Mode

From OSDev Wiki
Jump to navigation Jump to search

Virtual 8086 mode is a sub-mode of Protected mode. In short, Virtual 8086 mode is whereby the CPU (in protected mode) is running a "Emulated" 16bit Real Mode machine.

Entering V86

The CPU is executing in virtual 86 mode when the VM bit (bit 17) is set in the EFLAGS register. If you want to enter virtual 86 mode you must set this bit to 1. A way of modifying the EFLAGS register is to use the PUSHF and POPF instructions, but these instructions are for user space and cannot modify supervisor flags. The only way to set the VM flag is to use the iret instruction. This instruction is normally used to return from an interrupt. When IRET is called with the VM=1 in the stack EFLAGS (the context being returned to is V86), the interrupt stack frame will contain segments ES, DS, FS, and GS, so that they can be set before entry.

A task gate can also be used to enter V86. This allows setting the segment registers. It is probably not necessary to do it this way unless the OS is using hardware multitasking.

Fig15-3.gif

V86 Problem

The most common problem with v86 mode is that you can't enter Protected mode from inside of a v86 task. In other words, if you are running Windows or have emm386 in memory, you can't do a "raw" switch into protected mode (it causes an exception). DOS extenders worked around that problem using either VCPI or DPMI interfaces to switch into pmode (actually, promoting their V86 task as a 'regular' user task). For an OS programmer such interfaces are simply useless as they're part of another OS.

There are a few other more "technical" problems people have when using v86 mode, mostly because v86 has some instructions "emulated" by what's known as a v86-monitor program, as the CPU is in protected mode, some instructions are high up on the security/protection level and running those directly would cause no-end of trouble for the OS.

Detecting v8086

EFLAGS.VM is NEVER pushed onto the stack if the V86 task uses PUSHFD. You should check if CR0.PE=1 and then assume it's V86 if that bit is set.

detect_v86:
   smsw    ax
   and     eax,1           ;CR0.PE bit
   ret

VM mode detection is mainly useful when writing DOS extenders or other programs that could be started either in plain real mode or in virtual mode from a protected mode system. An 'ordinary' bootloader shouldn't worry about this since the BIOS will not set up VM86 to read the bootsector ;)

Usage

VM86 can be very useful if one needs access to BIOS functions while in Protected mode. It is in fact necessary in order to set up video mode, as many modern card/chipsets lack support for the VBE3 protected mode interface, so setting up a VM86 task that will perform the 'set video mode' call is the preferred method.

Kernels below 1MB

It has been suggested that you map your kernel to a 'high' logical address (e.g. 0xC0000000) to avoid VM86 tasks interfering with it. This is especially important with large kernels which leave no room for VM86 code below 1MB, or when larger programs are expected to run within the VM86 box.

If all that is needed is a BIOS interrupt wrapper, then the following should work:

  1. ensure that your 16bits code is on a separate page from any 32 bits code
  2. enable paging
  3. make kernel pages unwritable (and unreadable ?) for DPL3 and allow user-access only to those pages that contains your 16 bits code and pages that contains BIOS code or data.

Using VM86 for disk access

Though theoretically possible, it is probably not a good idea. Most BIOS disk access will include IRQ handlers, DMA transfers (uncontrollable from within your VM monitor), and may stick in VM86 task while the BIOS waits for an interrupt response while a 'good' driver would have let the CPU free for other processes.

Windows 9x suffered from system freezing during disk access. Often due to an INT13-through-VM86 problem.

See Also

Articles

Threads

External Links